package com.kobeliu.netty.websocket;

import com.a3test.component.idworker.IdWorkerConfigBean;
import com.a3test.component.idworker.Snowflake;
import com.google.gson.Gson;
import com.kobeliu.enums.MsgTypeEnum;
import com.kobeliu.netty.mq.MessageMQUtils;
import com.kobeliu.pojo.netty.ChatMsg;
import com.kobeliu.pojo.netty.DataContent;
import com.kobeliu.utils.GsonUtils;
import com.kobeliu.utils.LocalDateUtils;
import com.tencentcloudapi.eiam.v20210420.models.UserSearchCriteria;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 处理消息的处理器
 *
 * TextWebSocketFrame 消息的载体
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //用于记录和管理所有的用户端channel
    public static ChannelGroup  clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);




    /**
     * 捕获到异常
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        clients.remove(ctx.channel());
        String userId = UserChannelSession.getUserId(ctx.channel().id().asLongText());
        UserChannelSession.deleteChannelByUserId(userId,ctx.channel());
        UserChannelSession.removeLongIdAndUserId(userId,ctx.channel().id().asLongText());
        //关闭channel
        if(ctx!=null && ctx.channel()!=null){
            if(ctx.channel().isOpen()){
                ctx.channel().close();
            }
        }

    }

    //在客户端连接到服务端触发
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        //添加到channel，并且放入ChannelGroup中
        clients.add(ctx.channel());

//        String userId = UserChannelSession.getUserId(ctx.channel().id().asLongText());
//        if(userId != null){
//            UserChannelSession.putUserIdAndChannels(userId, ctx.channel());
//            UserChannelSession.putLongIdAndUserId(userId,ctx.channel().id().asLongText());
//        }
    }

    //关闭连接
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        //移除channel
        clients.remove(ctx.channel());

        String userId = UserChannelSession.getUserId(ctx.channel().id().asLongText());
        if(userId != null){
            UserChannelSession.deleteChannelByUserId(userId, ctx.channel());
            UserChannelSession.removeLongIdAndUserId(userId,ctx.channel().id().asLongText());
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

        String text = msg.text();
//        System.out.println("接收到的消息："+text);

        //获取当前用户连接的客户端channel
        Channel channel = ctx.channel();
//        String currentChannelLongId = channel.id().asLongText();
//        String currentChannelShortId = channel.id().asShortText();

//        System.out.println("currentChannelLongId"+currentChannelLongId);
//        System.out.println("currentChannelShortId"+currentChannelShortId);

//        TextWebSocketFrame replayMsg = new TextWebSocketFrame("当前客户端的Id为："+currentChannelLongId);


        //1.解析收到的信息
        DataContent dataContent = GsonUtils.stringToBean(text, DataContent.class);

        //2.拿到基本内容
        ChatMsg chatMsg = dataContent.getChatMsg();
        String msgText = chatMsg.getMsg();
        String receiverId = chatMsg.getReceiverId();
        String senderId = chatMsg.getSenderId();
        //时间校准
        chatMsg.setChatTime(LocalDateTime.now());
        Integer msgType = chatMsg.getMsgType();
        if(msgType == MsgTypeEnum.CONNECT_INIT.getType()){
            //初始化channel会话
            //把用户Id和channelId管理起来
            UserChannelSession.putUserIdAndChannels(senderId,ctx.channel());
            UserChannelSession.putLongIdAndUserId(ctx.channel().id().asLongText(),senderId);
//            System.out.println("UserChannelSession.getUserId(senderId)"+UserChannelSession.getChannels(senderId).toString());
        }
        else if(msgType == MsgTypeEnum.WORDS.getType()
                || msgType == MsgTypeEnum.IMAGE.getType()
                || msgType== MsgTypeEnum.VIDEO.getType()
                || msgType == MsgTypeEnum.VOICE.getType()
                || msgType == MsgTypeEnum.RESUME.getType()
                || msgType == MsgTypeEnum.INVITE.getType()
                || msgType == MsgTypeEnum.MSG_INTERVIEW_ACCEPT.getType()
                || msgType == MsgTypeEnum.MSG_INTERVIEW_CANCEL.getType()
                || msgType == MsgTypeEnum.MSG_INTERVIEW_REFUSE.getType()
        ){
            //表情
            //从全局map中看receiver是否在线
            List<Channel> channels = UserChannelSession.getChannels(receiverId);
            if(channels==null || channels.size()==0){
                //代表短线 OR 断线
                chatMsg.setIsReceiverOnLine(false);
                //存db

            }else{
                chatMsg.setIsReceiverOnLine(true);

                // 雪花算法 生成 Id
                Snowflake snowflake = new Snowflake(new IdWorkerConfigBean());
                String sid = snowflake.nextId();
                chatMsg.setMsgId(sid);

                //发送消息
                for(Channel ch:channels){

                    if(msgType.equals(MsgTypeEnum.VOICE.getType())){
                        //语音未读
                        chatMsg.setIsRead(false);
                    }
                    dataContent.setChatMsg(chatMsg);

                    dataContent.setChatTime(LocalDateUtils.format(LocalDateTime.now(),LocalDateUtils.DATETIME_PATTERN_2));
                    TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(GsonUtils.object2String(dataContent));
                    ch.writeAndFlush(textWebSocketFrame);

                }
            }
            //发送消息到mq
            String json = new Gson().toJson(chatMsg);
//            new MessageMQUtils().sendMsg(json,MessageMQUtils.EXCHANGE_MSG,MessageMQUtils.SAVE_MSG_ROUTING_KEY);

            //发送消息到mq
            sendMsgToSave(json);
        }



        //若发送方在多个设备登录，自己的消息同步到其他设备
        List<Channel> channels = UserChannelSession
                .getMyOtherChannels(senderId,
                        ctx.channel().id().asLongText());

        if(channels!=null && !channels.isEmpty()){
            dataContent.setChatMsg(chatMsg);
            TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(GsonUtils.object2String(dataContent));
            for(Channel ch:channels){
                ch.writeAndFlush(textWebSocketFrame);
            }
        }

        //群发消息
//        for (Channel ch:clients){
//            channel.writeAndFlush(replayMsg);
//        }
        //或者
//        clients.writeAndFlush(replayMsg);
    }

    public static void sendMsgToSave(String msg) throws Exception {
        MessageMQUtils messageMQUtils = new MessageMQUtils();
        messageMQUtils.sendMsg(msg,MessageMQUtils.EXCHANGE_MSG,MessageMQUtils.SAVE_MSG_ROUTING_KEY);
    }


}
